import { type Token, type RegularItem, TokenTypes } from './tokenizer.type'

export const tokenizer = (code) => {
  const leftBracket: RegularItem = {
    regular: /\(/,
    type: TokenTypes.LeftParen,
  }
  const rightBracket: RegularItem = {
    regular: /\)/,
    type: TokenTypes.RightParen,
  }
  const stringCtx: RegularItem = {
    regular: /[a-zA-Z]/,
    type: TokenTypes.Name,
  }
  const unmberCtx: RegularItem = {
    regular: /[0-9]/,
    type: TokenTypes.Number,
  }
  const spaceCtx: RegularItem = {
    regular: /\s/,
    type: TokenTypes.Space,
  }
  const singleQuote: RegularItem = {
    regular: /'/,
    type: TokenTypes.String,
  }
  const tokens: Token[] = []
  let poiner = 0
  const codeLength = code.length
  while (poiner < codeLength) {
    let chart = code[poiner]
    if (spaceCtx.regular.test(chart)) {
      poiner++
      continue
    }
    if (leftBracket.regular.test(chart)) {
      tokens.push({
        type: leftBracket.type,
        value: chart,
      })
      poiner++
      continue
    }
    if (rightBracket.regular.test(chart)) {
      tokens.push({
        type: rightBracket.type,
        value: chart,
      })
      poiner++
      continue
    }
    if (stringCtx.regular.test(chart)) {
      let value = ''
      while (stringCtx.regular.test(chart) && poiner < codeLength) {
        value += chart
        poiner++
        chart = code[poiner]
      }
      tokens.push({
        type: stringCtx.type,
        value: value,
      })
      continue
    }
    if (unmberCtx.regular.test(chart)) {
      let value = ''
      while (unmberCtx.regular.test(chart) && poiner < codeLength) {
        value += chart
        poiner++
        chart = code[poiner]
      }
      tokens.push({
        type: unmberCtx.type,
        value: value,
      })
      continue
    }
    if (singleQuote.regular.test(chart)) {
      let value = ''
      poiner++
      chart = code[poiner]
      while (!singleQuote.regular.test(chart) && poiner < codeLength) {
        value += chart
        poiner++
        chart = code[poiner]
      }
      if (!singleQuote.regular.test(chart)) {
        throw new Error('字符串未正常结束，请检查')
      }
      poiner++
      tokens.push({
        type: singleQuote.type,
        value: value,
      })
      continue
    }
    throw new TypeError('未知字符:' + chart)
  }
  return tokens
}
